from otree.api import Currency as c, currency_range from . import models from ._builtin import Page, WaitPage from .models import Constants import random from random import shuffle import itertools from decimal import * def vars_for_all_templates(self): return { 'condition': self.participant.vars['condition'], 'type': self.participant.vars['type'] } class GroupWait(WaitPage): template_name = 'cost_reporting_task_ss/CWaitPage.html' body_text = "Please wait briefly while the other Manager arrives..." title_text = "" group_by_arrival_time = True # Group by time but make sure to get Mgr A and Mgr B separated so roles don't get flip-flopped def get_players_for_group(self, waiting_players): if self.round_number == 1: # In first round, just group first Mgr A and B since no history exists mgrs_A = [p for p in waiting_players if self.participant.vars['type'] == 1] mgrs_B = [p for p in waiting_players if self.participant.vars['type'] == 2] if len(mgrs_A) > 0 and len(mgrs_B) > 0: return [mgrs_A[0], mgrs_B[0]] else: mgrs_A = [p for p in waiting_players if self.participant.vars['type'] == 1] mgrs_B = [p for p in waiting_players if self.participant.vars['type'] == 2] num_waiting_A = len(mgrs_A) num_waiting_B = len(mgrs_B) if num_waiting_A > 0 and num_waiting_B > 0: #As long as one Mgr A and one Mgr B waiting, see if we can form a group... i = 0 while i < num_waiting_A: mgr_match_A = mgrs_A[i] # Take the first waiting mgr A mgr_partners_A = [p.partner_id for p in mgr_match_A.in_previous_rounds()] # Get all their previous partners j = 0 # Start with the first waiter who is not the 'source' matcher while j < num_waiting_B: # While there are Mgr Bs left to check mgr_potential_partner = mgrs_B[j].participant_id # The first potential new partner # Compare source matcher's previous partners with first potential partner to see if they can match k = 0 match_count = 0 while k < len(mgr_partners_A): # To loop through previous partners if mgr_partners_A[k] == mgr_potential_partner or mgr_potential_partner == mgr_match_A.participant_id: # See if previous partner id matches first potential match match_count += 1 # If so flag it k += 1 if match_count == 0: # If we got all the way through without finding they had previously matched... return [mgrs_A[i], mgrs_B[j]] # Match them! j += 1 i += 1 # Move on to the next waiter to see if they can find a match class Pre_Task(Page): def is_displayed(self): if self.round_number == 1: return True else: return False def before_next_page(self): self.player.condition = self.participant.vars['condition'] self.player.type = self.participant.vars['type'] class ChatWait(WaitPage): template_name = 'cost_reporting_task/CWaitPage.html' body_text = "Please wait briefly while the other Manager arrives..." title_text = "" class Cost_Info(Page): form_model = models.Player form_fields = ['chat_time'] class ReportA(Page): form_model = models.Player form_fields = ['report_A', 'report_B'] def is_displayed(self): if self.player.type == 1: return True else: return False # Update partner's data def before_next_page(self): models.Player.objects.filter(id=self.player.partner_id).update(report_A_partner=self.player.report_A, report_B_partner=self.player.report_B) class WaitReportA(WaitPage): template_name = 'cost_reporting_task/CWaitPage.html' body_text = "Please wait briefly while the other Manager makes their cost reports..." title_text = "" class ReportB(Page): form_model = models.Player form_fields = ['report_A', 'report_B'] def is_displayed(self): if self.player.type == 2: return True else: return False # Update partner's data def before_next_page(self): models.Player.objects.filter(id=self.player.partner_id).update(report_A_partner=self.player.report_A, report_B_partner=self.player.report_B) # Can determine outcomes now that Manager B has reported, so do that before moving to results page # mgr_data = models.Player.objects.get(id=self.player.id) if self.player.report_A != self.player.report_A_partner: audit_A = 1 else: audit_A = 0 if self.player.report_B != self.player.report_B_partner: audit_B = 1 else: audit_B = 0 self.player.audit_flag_A = audit_A self.player.audit_flag_B = audit_B if audit_A == 1 and self.player.report_A != self.player.actual_A: self.player.bust_A = 1 else: self.player.bust_A = 0 if audit_B == 1 and self.player.report_B != self.player.actual_B: self.player.bust_B = 1 else: self.player.bust_B = 0 if audit_A == 1 and self.player.report_A_partner != self.player.actual_A: self.player.bust_A_partner = 1 else: self.player.bust_A_partner = 0 if audit_B == 1 and self.player.report_B_partner != self.player.actual_B: self.player.bust_B_partner = 1 else: self.player.bust_B_partner = 0 if self.player.condition < 5 or self.player.condition > 6: #No shared interest # This is always Manager B hitting this page, so easy to know whose data to look at if audit_A == 0 and self.player.report_A_partner > self.player.actual_A: self.player.slack_A = self.player.report_A_partner - self.player.actual_A self.player.slack_dol_A = Decimal(self.player.slack_A / 5000) * Decimal(0.25) else: self.player.slack_A = 0 self.player.slack_dol_A = 0.00 if audit_B == 0 and self.player.report_B > self.player.actual_B: self.player.slack_B = self.player.report_B_partner - self.player.actual_B self.player.slack_dol_B = Decimal(self.player.slack_B / 5000) * Decimal(0.25) else: self.player.slack_B = 0 self.player.slack_dol_B = 0.00 # Also need to update reporting outcomes, potential lira, and potential comp... if self.player.bust_A == 1 or self.player.bust_B == 1: potential_lira = 0 else: # If nothing is audited, they either got some slack plus salary or just salary if self.player.audit_flag_A == 0 and self.player.audit_flag_B == 0: if self.player.slack_B > 0: potential_lira = self.player.slack_B + 30000 else: potential_lira = 30000 # If only their project was audited (and they didn't get busted), they got an audit bonus/salary elif self.player.audit_flag_B == 1 and self.player.audit_flag_A == 0: potential_lira = 120000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 0: # Could have slack if self.player.slack_B > 0: potential_lira = self.player.slack_B + 120000 else: potential_lira = 120000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 1: potential_lira = 210000 potential_comp = Decimal(potential_lira / 5000) * Decimal(0.25) self.player.lira = potential_lira self.player.potential_comp = potential_comp # Same for Manager A... if self.player.bust_A_partner == 1 or self.player.bust_B_partner == 1: potential_lira_partner = 0 else: # If nothing is audited, they either got some slack plus salary or just salary if self.player.audit_flag_A == 0 and self.player.audit_flag_B == 0: if self.player.slack_A > 0: potential_lira_partner = self.player.slack_A + 30000 else: potential_lira_partner = 30000 # If only their project was audited (and they didn't get busted), they got an audit bonus/salary elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 0: potential_lira_partner = 120000 elif self.player.audit_flag_B == 1 and self.player.audit_flag_A == 0: # Could have slack if self.player.slack_A > 0: potential_lira_partner = self.player.slack_A + 120000 else: potential_lira_partner = 120000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 1: potential_lira_partner = 210000 potential_comp_partner = Decimal(potential_lira_partner / 5000) * Decimal(0.25) self.player.lira_partner = potential_lira_partner self.player.potential_comp_partner = potential_comp_partner else: #Shared interest with other conversion rate # This is always Manager B hitting this page, so easy to know whose data to look at # Shared interest, have to split the slack - but leave the raw slack as-is if audit_A == 0 and self.player.report_A_partner > self.player.actual_A: self.player.slack_A = self.player.report_A_partner - self.player.actual_A self.player.slack_dol_A = Decimal(self.player.slack_A / 5000) * Decimal(0.50) else: self.player.slack_A = 0 self.player.slack_dol_A = 0.00 if audit_B == 0 and self.player.report_B > self.player.actual_B: self.player.slack_B = self.player.report_1B_partner - self.player.actual_B self.player.slack_dol_B = Decimal(self.player.slack_B / 5000) * Decimal(0.50) else: self.player.slack_B = 0 self.player.slack_dol_B = 0.00 # Also need to update reporting outcomes, potential lira, and potential comp... if self.player.bust_A == 1 or self.player.bust_B == 1: potential_lira = 0 else: # If nothing is audited, they either got some slack plus salary or just salary if self.player.audit_flag_A == 0 and self.player.audit_flag_B == 0: if self.player.slack_B > 0: potential_lira = int(self.player.slack_B / 2) + 15000 else: potential_lira = 15000 # If only their project was audited (and they didn't get busted), they got an audit bonus/salary elif self.player.audit_flag_B == 1 and self.player.audit_flag_A == 0: potential_lira = 60000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 0: # Could have slack if self.player.slack_B > 0: potential_lira = int(self.player.slack_B / 2) + 60000 else: potential_lira = 60000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 1: potential_lira = 105000 potential_comp = Decimal(potential_lira / 5000) * Decimal(0.50) self.player.lira = potential_lira self.player.potential_comp = potential_comp # Same for Manager A... if self.player.bust_A_partner == 1 or self.player.bust_B_partner == 1: potential_lira_partner = 0 else: # If nothing is audited, they either got some slack plus salary or just salary if self.player.audit_flag_A == 0 and self.player.audit_flag_B == 0: if self.player.slack_A > 0: potential_lira_partner = int(self.player.slack_A / 2) + 15000 else: potential_lira_partner = 15000 # If only their project was audited (and they didn't get busted), they got an audit bonus/salary elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 0: potential_lira_partner = 60000 elif self.player.audit_flag_B == 1 and self.player.audit_flag_A == 0: # Could have slack if self.player.slack_A > 0: potential_lira_partner = int(self.player.slack_A / 2) + 60000 else: potential_lira_partner = 60000 elif self.player.audit_flag_A == 1 and self.player.audit_flag_B == 1: potential_lira_partner = 105000 potential_comp_partner = Decimal(potential_lira_partner / 5000) * Decimal(0.50) self.player.lira_partner = potential_lira_partner self.player.potential_comp_partner = potential_comp_partner if self.player.lira == 0: self.player.slack_B = 0 self.player.slack_dol_B = 0.00 if self.player.lira_partner == 0: self.player.slack_A = 0 self.player.slack_dol_A = 0.00 # ...then update Manager A's stuff on the way out models.Player.objects.filter(id=self.player.partner_id).update(audit_flag_A=self.player.audit_flag_A, audit_flag_B=self.player.audit_flag_B, slack_A=self.player.slack_A, slack_dol_A=self.player.slack_dol_A, slack_B=self.player.slack_B, slack_dol_B=self.player.slack_dol_B, bust_A=self.player.bust_A_partner, bust_A_partner=self.player.bust_A, bust_B=self.player.bust_B_partner, bust_B_partner=self.player.bust_B, lira=self.player.lira_partner, potential_comp=self.player.potential_comp_partner, lira_partner=self.player.lira, potential_comp_partner=self.player.potential_comp) class WaitReportB(WaitPage): template_name = 'cost_reporting_task/CWaitPage.html' body_text = "Please wait briefly while the other Manager makes their cost reports..." title_text = "" class Reporting_Results(Page): def vars_for_template(self): return {'slack_A_share': int(self.player.slack_A / 2), 'slack_B_share': int(self.player.slack_B / 2)} page_sequence = [ GroupWait, Pre_Task, ChatWait, Cost_Info, ReportA, WaitReportA, ReportB, WaitReportB, Reporting_Results ]